﻿using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace B.S.BaseData.ReadAPI
{
    /// <summary>
    /// JwtToken 生成器
    /// </summary>
    public class TokenHelper
    {
        private readonly IConfiguration _configuration;
        private readonly JwtSecurityTokenHandler _jwtSecurityTokenHandler;

        /// <summary>
        /// 构造函数注入
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="jwtSecurityTokenHandler"></param>
        public TokenHelper(IConfiguration configuration, JwtSecurityTokenHandler jwtSecurityTokenHandler)
        {
            _configuration = configuration;
            _jwtSecurityTokenHandler = jwtSecurityTokenHandler;
        }

        /// <summary>
        /// 创建加密JwtToken
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public string CreateJwtToken<T>(T user)
        {
            var signingAlgorithm = SecurityAlgorithms.HmacSha256;
            //CreateClaimList  将用户信息 加载到 载荷 当中
            var claimList = this.CreateClaimList(user);
            //Signature
            //取出私钥并以utf8编码字节输出
            var secretByte = Encoding.UTF8.GetBytes(_configuration["Authentication:SecretKey"]);
            //使用非对称算法对私钥进行加密
            var signingKey = new SymmetricSecurityKey(secretByte);
            //使用HmacSha256来验证加密后的私钥生成数字签名
            var signingCredentials = new SigningCredentials(signingKey, signingAlgorithm);
            //生成Token
            var token = new JwtSecurityToken(
                issuer: _configuration["Authentication:Issuer"], //发布者
                audience: _configuration["Authentication:Audience"], //接收者
                claims: claimList, //存放的用户信息
                notBefore: DateTime.UtcNow, //发布时间
                expires: DateTime.UtcNow.AddDays(1), //有效期设置为1天
                signingCredentials //数字签名
            );
            //生成字符串token
            var tokenStr = new JwtSecurityTokenHandler().WriteToken(token);
            return tokenStr;
        }


        /// <summary>
        /// 创建包含用户信息的ClaimList
        /// </summary>
        /// <param name="authUser"></param>
        /// <returns></returns>
        private List<Claim> CreateClaimList<T>(T authUser)
        {
            var classType = typeof(T);
            //Claim 载荷的类 List
            //GetProperties 获取类型下所有的属性
            return classType.GetProperties().Select(item => new Claim(item.Name, Convert.ToString(item.GetValue(authUser)) ?? string.Empty)).ToList();
        }

        /// <summary>
        /// 将Token转换为对象
        /// </summary>
        /// <param name="token"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T ConvertTokenToObj<T>(string token) where T : new()
        {
            var objA = new T();
            var jwtToken = _jwtSecurityTokenHandler.ReadJwtToken(token);

            foreach (var claim in jwtToken.Claims)
            {
                // 尝试匹配属性
                var property = typeof(T).GetProperties()
                    .FirstOrDefault(p => string.Equals(p.Name, claim.Type, StringComparison.OrdinalIgnoreCase));

                if (property == null || !property.CanWrite) continue;
                var targetType = property.PropertyType;

                // 尝试将 claim.Value 转换为目标属性的类型
                var convertedValue = Convert.ChangeType(claim.Value, targetType);
                property.SetValue(objA, convertedValue);
            }

            return objA;
        }

    }
}
